/************************************************************
** @brief   : app_xbutton
** @author  : vandoul
** @github  : https://gitee.com/vandoul
** @date    : 2022-01
** @version : v1.0.0
** @note    : app_xbutton.c
***********************************************************/

#include <rtdevice.h>
#include "xbutton.h"

/* defined the BTN0 pin: PA4 */
#define BTN0_PIN    29
/* defined the BTN1 pin: PA5 */
#define BTN1_PIN    30
/* defined the BTN2 pin: PA6 */
#define BTN2_PIN    31
/* defined the BTN3 pin: PA0 */
#define BTN3_PIN    23

static uint32_t xbutton_get_ms(void)
{
    return rt_tick_get_millisecond();
}
static rt_event_t btn_event;
static void btn_send_event(void *p)
{
    rt_event_send(btn_event, (uint32_t)p);
}
#define BTN0_EVENT_FLAG         (1<<0)
#define BTN1_EVENT_FLAG         (1<<1)
#define BTN2_EVENT_FLAG         (1<<2)
#define BTN3_EVENT_FLAG         (1<<3)
#define BTN_ALL_EVENT_FLAG      (BTN1_EVENT_FLAG|BTN2_EVENT_FLAG|BTN3_EVENT_FLAG|BTN0_EVENT_FLAG)
static void btn_init(void)
{
    btn_event = rt_event_create("btn_evt", RT_IPC_FLAG_FIFO);
    if(btn_event == RT_NULL) {
        rt_kprintf("create btn event failed!\r\n");
        return ;
    }
    rt_pin_mode(BTN0_PIN, PIN_MODE_INPUT_PULLUP);
    rt_pin_mode(BTN1_PIN, PIN_MODE_INPUT_PULLUP);
    rt_pin_mode(BTN2_PIN, PIN_MODE_INPUT_PULLUP);
    rt_pin_mode(BTN3_PIN, PIN_MODE_INPUT);
    rt_pin_attach_irq(BTN0_PIN, PIN_IRQ_MODE_RISING_FALLING, btn_send_event, (void *)BTN0_EVENT_FLAG);
    rt_pin_attach_irq(BTN1_PIN, PIN_IRQ_MODE_RISING_FALLING, btn_send_event, (void *)BTN1_EVENT_FLAG);
    rt_pin_attach_irq(BTN2_PIN, PIN_IRQ_MODE_RISING_FALLING, btn_send_event, (void *)BTN2_EVENT_FLAG);
    rt_pin_attach_irq(BTN3_PIN, PIN_IRQ_MODE_RISING_FALLING, btn_send_event, (void *)BTN3_EVENT_FLAG);
    rt_pin_irq_enable(BTN0_PIN, PIN_IRQ_ENABLE);
    rt_pin_irq_enable(BTN1_PIN, PIN_IRQ_ENABLE);
    rt_pin_irq_enable(BTN2_PIN, PIN_IRQ_ENABLE);
    rt_pin_irq_enable(BTN3_PIN, PIN_IRQ_ENABLE);
}
inline static rt_uint8_t read_btn0_level(void)
{
    return rt_pin_read(BTN0_PIN);
}
inline static rt_uint8_t read_btn1_level(void)
{
    return rt_pin_read(BTN1_PIN);
}
inline static rt_uint8_t read_btn2_level(void)
{
    return rt_pin_read(BTN2_PIN);
}
inline static rt_uint8_t read_btn3_level(void)
{
    return rt_pin_read(BTN3_PIN);
}
#define SMPLPAGE_EVENT_PREV         (1<<0)
#define SMPLPAGE_EVENT_OK           (1<<1)
#define SMPLPAGE_EVENT_NEXT         (1<<2)
#define SMPLPAGE_EVENT_BACK         (1<<3)
static const char *btn_str[] = {
    "btn_prev","btn_ok","btn_next","btn_back"
};
extern rt_event_t simple_page_evt;
static void button_event_callback(int index, xbutton_event_t evt)
{
    rt_kprintf("%s:%s!\r\n", btn_str[index], xbutton_event_code_to_string(evt));
    if(simple_page_evt != RT_NULL) {
        switch(index) {
            case 0: {
                rt_event_send(simple_page_evt, SMPLPAGE_EVENT_PREV);
            }
            break;
            case 1: {
                rt_event_send(simple_page_evt, SMPLPAGE_EVENT_OK);
            }
            break;
            case 2: {
                rt_event_send(simple_page_evt, SMPLPAGE_EVENT_NEXT);
            }
            break;
            case 3: {
                rt_event_send(simple_page_evt, SMPLPAGE_EVENT_BACK);
            }
            break;
        }
    }
}
static int button_wait_event(int *level)
{
    uint32_t evt;
    int index = -1;
    if(rt_event_recv(btn_event, BTN_ALL_EVENT_FLAG, RT_EVENT_FLAG_OR, rt_tick_from_millisecond(50), &evt) == RT_EOK) {
        if(evt & BTN0_EVENT_FLAG) {
            rt_event_recv(btn_event, BTN0_EVENT_FLAG, RT_EVENT_FLAG_AND|RT_EVENT_FLAG_CLEAR, 0, RT_NULL);
            index = 0;
        } else if(evt & BTN1_EVENT_FLAG) {
            rt_event_recv(btn_event, BTN1_EVENT_FLAG, RT_EVENT_FLAG_AND|RT_EVENT_FLAG_CLEAR, 0, RT_NULL);
            index = 1;
        } else if(evt & BTN2_EVENT_FLAG) {
            rt_event_recv(btn_event, BTN2_EVENT_FLAG, RT_EVENT_FLAG_AND|RT_EVENT_FLAG_CLEAR, 0, RT_NULL);
            index = 2;
        } else if(evt & BTN3_EVENT_FLAG) {
            rt_event_recv(btn_event, BTN3_EVENT_FLAG, RT_EVENT_FLAG_AND|RT_EVENT_FLAG_CLEAR, 0, RT_NULL);
            index = 3;
        } else {
            rt_event_recv(btn_event, BTN_ALL_EVENT_FLAG, RT_EVENT_FLAG_OR|RT_EVENT_FLAG_CLEAR, 0, RT_NULL);
            index = -1;
        }
    }
    if(level) {
        switch(index) {
        case 0: {
            *level = read_btn0_level();
        }
        break;
        case 1: {
            *level = read_btn1_level();
        }
        break;
        case 2: {
            *level = read_btn2_level();
        }
        break;
        case 3: {
            *level = read_btn3_level();
        }
        break;
        default: {
            *level = -1;
        }
        break;
        }
    }
    return index;
}
rt_event_t rt_event_find(const char *name);
static void user_xbutton_task(void *p)
{
//    simple_page_evt = rt_event_find("smplPage");
//    if(simple_page_evt == RT_NULL) {
//        rt_kprintf("can't found simple_page_evt\r\n");
//    }
    btn_init();
    xbutton_init(4, xbutton_get_ms, button_wait_event);
    xbutton_add(0, 0);
    xbutton_add(1, 0);
    xbutton_add(2, 0);
    xbutton_add(3, 0);
//    xbutton_add_button_event(0, XBUTTON_DOWN, button_event_callback);
//    xbutton_add_button_event(0, XBUTTON_DOUBLE, button_event_callback);
//    xbutton_add_button_event(0, XBUTTON_LONG, button_event_callback);
//    xbutton_add_button_event(1, XBUTTON_EVENT_ALL, button_event_callback);
//    xbutton_add_button_event(2, XBUTTON_EVENT_ALL, button_event_callback);
    xbutton_add_button_event(0, XBUTTON_DOWN, button_event_callback);
    xbutton_add_button_event(1, XBUTTON_DOWN, button_event_callback);
    xbutton_add_button_event(2, XBUTTON_DOWN, button_event_callback);
    xbutton_add_button_event(3, XBUTTON_DOWN, button_event_callback);
    while(1) {
        xbutton_process();
    }
}
void user_xbutton_task_init(void)
{
    rt_thread_t tid;
    tid = rt_thread_create("btn", user_xbutton_task, RT_NULL, 2048, 10, 10);
    if(tid != RT_NULL) {
        rt_thread_startup(tid);
    }
}


